package com.aloha.auth.support.impl;

import com.aloha.auth.exception.AuthException;
import com.aloha.auth.support.AuthUtils;
import com.aloha.auth.support.AuthValidator;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * 路由权限校验
 *
 * @author zhdai
 * @date 2023/11/10 14:27
 */
public class RouterAuthValidator implements AuthValidator {

    private final List<RouterAuth> routerAuths = new ArrayList<>();

    private final AntPathMatcher matcher = new AntPathMatcher();

    @Override
    public boolean validate(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) {
        String path = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        RouterAuth routerAuth = null;
        for (RouterAuth auth : routerAuths) {
            if (matcher.match(auth.getPattern(), path)) {
                routerAuth = auth;
                break;
            }
        }
        if (routerAuth != null && !routerAuth.match()) {
            throw new AuthException(401, "没有权限");
        }
        return true;
    }

    public RouterAuthValidator addMatch(String pattern, Predicate<Object> predicate) {
        routerAuths.add(new RouterAuth(pattern, predicate));
        return this;
    }

    public static class RouterAuth {

        private final String pattern;

        private final Predicate<Object> predicate;

        private RouterAuth(String pattern, Predicate<Object> predicate) {
            this.pattern = pattern;
            this.predicate = predicate;
        }

        public boolean match() {
            return predicate.test(AuthUtils.getPermsList());
        }

        public String getPattern() {
            return pattern;
        }

        public Predicate<?> getPredicate() {
            return predicate;
        }
    }
}
